package com.sssre.business.service.impl;

import com.sssre.business.domain.BusBpmnInfo;
import com.sssre.business.domain.BusCarPackageAudit;
import com.sssre.business.domain.BusServiceItem;
import com.sssre.business.exception.ServiceValidException;
import com.sssre.business.mapper.BusCarPackageAuditMapper;
import com.sssre.business.mapper.BusServiceItemMapper;
import com.sssre.business.service.IBusBpmnInfoService;
import com.sssre.business.service.IBusCarPackageAuditService;
import com.sssre.business.vo.BusCarPackageAuditVO;
import com.sssre.business.vo.HistoryVO;
import com.sssre.common.utils.DateUtils;
import com.sssre.common.utils.PageUtils;
import com.sssre.common.utils.SecurityUtils;
import com.sssre.system.mapper.SysRoleMapper;
import org.activiti.bpmn.model.BpmnModel;
import org.activiti.engine.HistoryService;
import org.activiti.engine.RepositoryService;
import org.activiti.engine.RuntimeService;
import org.activiti.engine.TaskService;
import org.activiti.engine.history.HistoricProcessInstance;
import org.activiti.engine.history.HistoricTaskInstance;
import org.activiti.engine.repository.ProcessDefinition;
import org.activiti.engine.runtime.ProcessInstance;
import org.activiti.engine.task.Comment;
import org.activiti.engine.task.Task;
import org.activiti.image.impl.DefaultProcessDiagramGenerator;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.io.InputStream;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 套餐审核Service业务层处理
 *
 * @author 浪兎兎
 * @date 2025-05-09
 */
@Service
public class BusCarPackageAuditServiceImpl implements IBusCarPackageAuditService {
    @Autowired
    private BusCarPackageAuditMapper busCarPackageAuditMapper;
    @Autowired
    private BusServiceItemMapper busServiceItemMapper;
    @Autowired
    private SysRoleMapper sysRoleMapper;
    @Autowired
    private RepositoryService repositoryService;
    @Autowired
    private RuntimeService runtimeService;
    @Autowired
    private TaskService taskService;
    @Autowired
    private HistoryService historyService;
    @Autowired
    private IBusBpmnInfoService busBpmnInfoService;

    /**
     * 查询套餐审核
     *
     * @param id 套餐审核主键
     * @return 套餐审核
     */
    @Override
    public BusCarPackageAudit selectBusCarPackageAuditById(Long id) {
        return busCarPackageAuditMapper.selectBusCarPackageAuditById(id);
    }

    /**
     * 查询套餐审核列表
     *
     * @param busCarPackageAudit 套餐审核
     * @return 套餐审核
     */
    @Override
    public List<BusCarPackageAudit> selectBusCarPackageAuditList(BusCarPackageAudit busCarPackageAudit) {
        return busCarPackageAuditMapper.selectBusCarPackageAuditList(busCarPackageAudit);
    }

    /**
     * 新增套餐审核
     *
     * @param busCarPackageAudit 套餐审核
     * @return 结果
     */
    @Override
    public int insertBusCarPackageAudit(BusCarPackageAudit busCarPackageAudit) {
        busCarPackageAudit.setCreateTime(DateUtils.getNowDate());
        return busCarPackageAuditMapper.insertBusCarPackageAudit(busCarPackageAudit);
    }

    /**
     * 修改套餐审核
     *
     * @param busCarPackageAudit 套餐审核
     * @return 结果
     */
    @Override
    public int updateBusCarPackageAudit(BusCarPackageAudit busCarPackageAudit) {
        return busCarPackageAuditMapper.updateBusCarPackageAudit(busCarPackageAudit);
    }

    /**
     * 批量删除套餐审核
     *
     * @param ids 需要删除的套餐审核主键
     * @return 结果
     */
    @Override
    public int deleteBusCarPackageAuditByIds(Long[] ids) {
        return busCarPackageAuditMapper.deleteBusCarPackageAuditByIds(ids);
    }

    /**
     * 删除套餐审核信息
     *
     * @param id 套餐审核主键
     * @return 结果
     */
    @Override
    public int deleteBusCarPackageAuditById(Long id) {
        // 校验数据合法性
        if (id == null) {
            throw new ServiceValidException("非法参数");
        }
        // 查询原始对象
        BusCarPackageAudit busCarPackageAudit = busCarPackageAuditMapper.selectBusCarPackageAuditById(id);
        if (busCarPackageAudit == null) {
            throw new ServiceValidException("非法参数");
        }
        // 状态合法性校验：只有审核中才可以撤销
        Integer status = busCarPackageAudit.getStatus();
        if (status.equals(BusCarPackageAudit.STATUS_IN_PROGRESS)) {
            throw new ServiceValidException("只有审核中的才可以撤销");
        }
        // 更改状态为审核撤销
        busCarPackageAuditMapper.updateStatus(id, BusCarPackageAudit.STATUS_CANCEL);
        busServiceItemMapper.updateStatus(busCarPackageAudit.getServiceItemId(), BusServiceItem.AUDIT_STATUS_INIT);
        // 撤销流程实例
        runtimeService.deleteProcessInstance(busCarPackageAudit.getInstanceId(), "用户撤销");
        return 1;
    }

    /**
     * 查看图片
     *
     * @param id 主键
     * @return 结果
     */
    @Override
    public InputStream readResource(Long id) {
        // 数据安全性校验
        if (id == null) {
            throw new ServiceValidException("数据不能为空");
        }
        // 查询原始对象
        BusCarPackageAudit busCarPackageAudit = busCarPackageAuditMapper.selectBusCarPackageAuditById(id);
        if (busCarPackageAudit == null) {
            throw new ServiceValidException("非法参数");
        }
        // 查询流程实例
        String instanceId = busCarPackageAudit.getInstanceId();
        ProcessDefinition processDefinition = null;
        ProcessInstance processInstance = runtimeService.createProcessInstanceQuery()
                .processInstanceId(instanceId)
                .singleResult();
        // 获取当前流程
        List<String> activeActivityIds = Collections.emptyList();
        if (processInstance == null) {
            // 如果查不到流程实例，那么根据历史查
            HistoricProcessInstance historicProcessInstance = historyService.createHistoricProcessInstanceQuery()
                    .processInstanceId(instanceId)
                    .singleResult();
            processDefinition = repositoryService.createProcessDefinitionQuery()
                    .processDefinitionId(historicProcessInstance.getProcessDefinitionId())
                    .singleResult();
        } else {
            String processDefinitionId = processInstance.getProcessDefinitionId();
            processDefinition = repositoryService.createProcessDefinitionQuery()
                    .processDefinitionId(processDefinitionId)
                    .singleResult();
            runtimeService.getActiveActivityIds(instanceId);
        }
        // 使用插件转换
        DefaultProcessDiagramGenerator processDiagramGenerator = new DefaultProcessDiagramGenerator();
        BpmnModel bpmnModel = repositoryService.getBpmnModel(processDefinition.getId());
        return processDiagramGenerator.generateDiagram(bpmnModel,
                activeActivityIds,
                Collections.emptyList(),
                "宋体",
                "宋体",
                "宋体");
    }

    /**
     * 撤销审核流程
     *
     * @param id 主键
     * @return 结果
     */
    @Override
    @Transactional
    public int revoke(Long id) {
        // 数据安全性校验
        if (id == null) {
            throw new ServiceValidException("数据不能为空");
        }
        // 查询原始对象
        BusCarPackageAudit busCarPackageAudit = busCarPackageAuditMapper.selectBusCarPackageAuditById(id);
        if (busCarPackageAudit == null) {
            throw new ServiceValidException("非法参数");
        }
        // 判断状态为审核中才能撤销
        Integer status = busCarPackageAudit.getStatus();
        if (!status.equals(BusCarPackageAudit.STATUS_IN_PROGRESS)) {
            throw new ServiceValidException("只有审核中的流程才可以撤销");
        }
        // 删除流程实例
        runtimeService.deleteProcessInstance(busCarPackageAudit.getInstanceId(), "用户撤销");
        // 更改状态
        busServiceItemMapper.updateStatus(busCarPackageAudit.getServiceItemId(), BusServiceItem.AUDIT_STATUS_INIT);
        return busCarPackageAuditMapper.updateStatus(id, BusCarPackageAudit.STATUS_CANCEL);
    }

    /**
     * 查询历史审核任务
     *
     * @param id 主键
     * @return 结果
     */
    @Override
    public List<HistoryVO> historyList(Long id) {
        // 数据安全性校验
        if (id == null) {
            throw new ServiceValidException("数据不能为空");
        }
        // 查询原始对象
        BusCarPackageAudit busCarPackageAudit = busCarPackageAuditMapper.selectBusCarPackageAuditById(id);
        if (busCarPackageAudit == null) {
            throw new ServiceValidException("非法参数");
        }
        // 根据流程实例查询历史表
        List<HistoricTaskInstance> list = historyService.createHistoricTaskInstanceQuery()
                .processInstanceId(busCarPackageAudit.getInstanceId())
                .list();
        // 封装历史表VOs
        List<HistoryVO> vos = new ArrayList<>();
        for (HistoricTaskInstance historicTask : list) {
            Date startTime = historicTask.getStartTime();
            Date endTime = historicTask.getEndTime();
            Long workTimeInMillis = historicTask.getDurationInMillis();
            String name = historicTask.getName();
            String commit = "";
            // 批注需要独立获取
            List<Comment> taskComments = taskService.getTaskComments(historicTask.getId());
            if (taskComments.size() != 0) {
                commit = taskComments.get(0).getFullMessage();
            }
            HistoryVO historyVO = new HistoryVO(name, startTime, endTime, workTimeInMillis, commit);
            vos.add(historyVO);
        }
        return vos;
    }

    /**
     * 查询代办任务
     *
     * @param busCarPackageAudit 主键
     * @return 结果
     */
    @Override
    public List<BusCarPackageAudit> selectBusCarPackageAuditTodoList(BusCarPackageAudit busCarPackageAudit) {
        // 合法性校验
        BusBpmnInfo busBpmnInfo = busBpmnInfoService.selectBusBpmnInfoByType(BusCarPackageAudit.FLOW_AUDIT_TYPE);
        if (busBpmnInfo == null) {
            throw new RuntimeException("非法操作");
        }
        // 获取当前 User Id
        Long userId = SecurityUtils.getUserId();
        // 根据 id（审批人）获取任务列表
        List<Task> list = taskService.createTaskQuery()
                .processDefinitionKey(busBpmnInfo.getProcessDefinitionKey())
                .taskAssignee(userId.toString())
                .list();
        // 根据任务获取实例 id
        List<String> collect = list.stream().map(Task::getProcessInstanceId).collect(Collectors.toList());
        if (collect.size() == 0) {
            return new ArrayList<>();
        }
        // 根据这些实例 id 查询
        PageUtils.startPage();
        busCarPackageAudit.getParams().put("instanceIds", collect);
        return busCarPackageAuditMapper.selectBusCarPackageAuditListByInstanceIds(busCarPackageAudit);
    }

    /**
     * 查询审核任务已办列表
     *
     * @param busCarPackageAudit 查询参数
     * @return 结果
     */
    @Override
    public List<BusCarPackageAudit> selectBusCarPackageAuditDoneList(BusCarPackageAudit busCarPackageAudit) {
        // 合法性校验
        BusBpmnInfo busBpmnInfo = busBpmnInfoService.selectBusBpmnInfoByType(BusCarPackageAudit.FLOW_AUDIT_TYPE);
        if (busBpmnInfo == null) {
            throw new RuntimeException("非法操作");
        }
        // 获取当前 User Id
        Long userId = SecurityUtils.getUserId();
        // 根据 id（审批人）获取历史任务列表
        List<HistoricTaskInstance> list = historyService.createHistoricTaskInstanceQuery()
                .taskAssignee(userId.toString())
                .finished()
                .list();
        // 根据任务获取实例 id
        List<String> collect = list.stream().map(HistoricTaskInstance::getProcessInstanceId).collect(Collectors.toList());
        if (collect.size() == 0) {
            return new ArrayList<>();
        }
        // 根据这些实例 id 查询
        PageUtils.startPage();
        busCarPackageAudit.getParams().put("instanceIds", collect);
        return busCarPackageAuditMapper.selectBusCarPackageAuditListByInstanceIds(busCarPackageAudit);
    }

    /**
     * 审批
     *
     * @param vo 参数
     * @return 结果
     */
    @Override
    @Transactional
    public int approve(BusCarPackageAuditVO vo) {
        // 参数合法性验证
        if (vo == null) {
            throw new ServiceValidException("非法参数");
        }
        // 查询原始对象判断非空
        BusCarPackageAudit busCarPackageAudit = busCarPackageAuditMapper.selectBusCarPackageAuditById(vo.getId());
        if (busCarPackageAudit == null) {
            throw new ServiceValidException("非法参数");
        }
        // 判断状态是否为审核中
        Integer status = busCarPackageAudit.getStatus();
        if (!status.equals(BusCarPackageAudit.STATUS_IN_PROGRESS)) {
            throw new ServiceValidException("审核中的任务才能进行审批");
        }
        // 根据当前用户id和流程实例id查询一个任务
        Task task = taskService.createTaskQuery()
                .taskAssignee(SecurityUtils.getUserId().toString())
                .processInstanceId(busCarPackageAudit.getInstanceId())
                .singleResult();
        // 通过状态
        boolean success = vo.getAuditStatus() == 1;
        // 设置流程变量，添加批注
        StringBuilder sb = new StringBuilder();
        sb.append("审批意见-[")
                .append(SecurityUtils.getUsername())
                .append(":")
                .append(success ? "通过-审批意见：" : "拒绝-审批意见：")
                .append(vo.getAuditInfo() == null ? "无" : vo.getAuditInfo())
                .append("]");
        taskService.addComment(task.getId(), busCarPackageAudit.getInstanceId(), sb.toString());
        // 完成这个任务
        taskService.complete(task.getId(), new HashMap<String, Object>() {
            {
                this.put("success", vo.getAuditStatus() == 1);
            }
        });
        if (success) {
            // 如果为拒绝，那么同时修改服务项和审核实例的状态为审核拒绝
            busCarPackageAuditMapper.updateStatus(busCarPackageAudit.getId(), BusCarPackageAudit.STATUS_REJECT);
            busServiceItemMapper.updateStatus(busCarPackageAudit.getServiceItemId(), BusServiceItem.AUDIT_STATUS_REFUSE);
        } else {
            // 如果为同意，判断是否存在下一任务节点（方法就是再次根据流程实例查询），如果没有，同时修改服务项和审核实例的状态为审核通过
            Task task1 = taskService.createTaskQuery()
                    .processInstanceId(busCarPackageAudit.getInstanceId())
                    .singleResult();
            if (task1 == null) {
                busCarPackageAuditMapper.updateStatus(busCarPackageAudit.getId(), BusCarPackageAudit.STATUS_PASS);
                busServiceItemMapper.updateStatus(busCarPackageAudit.getServiceItemId(), BusServiceItem.AUDIT_STATUS_PASS);
            }
        }
        return 1;
    }
}
